// 测试线程退出处理函数 pthread_cleanup_push 与 pthread_cleanup_pop

#include <stdio.h>
#include <pthread.h>
#include <error.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>

void routine(void* args)
{
    char* msg = (char*) args;
    printf("%s\n", msg);
}

//测试 线程清理函数的执行时机
// 1 线程入口函数 返回
// 2 接收取消信号
// 3 调用pthread_exit()线程终止函数

void* start_routine(void* args)
{
    //注册线程清理函数
    //void (routine)(void*)
    pthread_cleanup_push(routine, "111");
    pthread_cleanup_push(routine, "222");
    pthread_cleanup_push(routine, "333");

    pthread_cleanup_pop(1); //不会终止线程

    //线程的执行逻辑
    printf("new thread start!\n");
    sleep(3);   //主线程发送取消请求，这是子线程在sleep在中断点直接响应，并且执行清理函数
    //参数为 结束是的返回值，可以通过join接收
    // pthread_exit(NULL);

    printf("new thread stop!\n");

    return NULL;
    //参数execute 不为0，不会终止线程，就可以执行清理函数又不会终止线程
    pthread_cleanup_pop(0);     //上面返回return 之后永远不会执行，但是要写，因为push pop是成对出现的
    pthread_cleanup_pop(0);
}

int main()
{
    //创建新线程
    pthread_t tid;
    int err = pthread_create(&tid, NULL, start_routine, NULL);
    if(err)
    {
        fprintf(stderr, "pthread_create failed");
        pthread_exit(NULL);
    }
    //让子线程有机会运行，防止主线程结束太快导致子线程没有就会进入运行，进程就结束
    sleep(1);
    pthread_cancel(tid);  //发送取消请求
    
    //等待子线程运行完
    pthread_join(tid, NULL);
    return 0;
}